﻿using Core.Infarastructure;
using Core.Infarastructure.Structs;
using Core.Models;
using StackAttack_WindowsFormApp.Animation;
using StackAttack_WindowsFormApp.DrawLogic;
using StackAttack_WindowsFormApp.Helpers;
using StackAttack_WindowsFormApp.PlayersData;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace StackAttack_WindowsFormApp.Engine
{
    class WindowsFormEngine
    {

        #region Fields
        private List<Image> sprites;
        private Image currentSprite;
        private int startIndexForSprites;
        private int endIndexForSprites;

        private Core.Logic.Engine _gameEngine;
        private List<Stack> _stacks;
        private Hero _hero;
        private bool[] buttonsPressed;
        private Graphics _graphics;

        private StackCreator _stackCreator;
        private HeroCreator _heroCreator;

        private List<System.Windows.Forms.KeyEventArgs> keysPressedWhileMoving;
        public System.Windows.Forms.Timer stackFalling;
        public System.Windows.Forms.Timer heroMoving;
        public System.Windows.Forms.Timer checkMoving;
        public System.Windows.Forms.Timer heroFalling;
        public System.Windows.Forms.Timer spriteChanging;
        private MainApp application;

        private DestroyingAnimation animation;

        private LeaderboardManager playersLeaderboard;

        #endregion Fieds

        public bool Paused { get; set; }


        public WindowsFormEngine(MainApp app, Graphics graphics, List<Stack> stacks, System.Drawing.Point heroCoordinates)
        {
            Initialization(app, graphics, stacks, heroCoordinates);         
        }


        #region Events
        void DrawingBox_Paint(object sender, PaintEventArgs e)
        {
            _stackCreator.FirstInitialize(e.Graphics, _stacks);
            _heroCreator.Create(e.Graphics, _gameEngine.HeroPosition, currentSprite);
            application.Score.Text = _hero.Score.ToString();
            
            

        }

        void checkMoving_Tick(object sender, EventArgs e)
        {

            _gameEngine.IsFreeSpaceUnderHero();
            _gameEngine.FixLowerStacks();
            _gameEngine.CheckSideBySideStacks();
            _gameEngine.CheckBorders();
            _gameEngine.FixStacksNearBorders();
            
            if (!_hero.Stacked)
            {
                _gameEngine.NearHeroStacks();
            }

            if (_hero.DestroyStackInAir)
            {

                animation.StartAnimation(new System.Drawing.Point(
                    _hero.CurrentPosition_X, _hero.CurrentPosition_Y - Constants.STACK_SIZE));
                _hero.DestroyStackInAir = false;
                
            }
            if (_gameEngine.CheckLines())
            {
                animation.LineExplosion = true;
                animation.StartAnimationForLine();
                stackFalling.Interval -= 5;
            }
            if (_hero.Killed)
            {
                AllTimersStop();
                playersLeaderboard.AddPlayerToFile(application.playerName.Text, _hero.Score);
                             
                application.Pause.Enabled = true;
                application.DrawingBox.Paint -= DrawingBox_Paint;
                
                application.DrawingBox.Image = Image.FromFile(PathFinder.GetFullPathToFile("Images\\game_over.png"));
                
                
            }
            _gameEngine.CheckIfNotFixed();

        }

        void heroMoving_Tick(object sender, EventArgs e)
        {
           
            
            if (!_hero.Stacked)
            {
                if (_hero.GoBack)
                {
                    _hero.BackJump();
                    return;
                }
                if (buttonsPressed[(int)Keys.Right] && !_hero.Stacked)
                {
                    if (!spriteChanging.Enabled)
                    {
                        startIndexForSprites = 3;
                        endIndexForSprites = 6;
                        spriteChanging.Start();
                    }
                    
                    _gameEngine.CheckRouteRight();
                    _gameEngine.CheckFreeSpaceUnderRightStack();
                    _hero.Move(Enums.Keys.KeyRight);
                    _gameEngine.CheckIsFreeRouteRight();

                    return;


                }
                if (buttonsPressed[(int)Keys.Left] && !_hero.Stacked)
                {

                    if (!spriteChanging.Enabled)
                    {
                        startIndexForSprites = 0;
                        endIndexForSprites = 3;
                        spriteChanging.Start();
                    }
                    _gameEngine.CheckRouteLeft();
                    _gameEngine.CheckFreeSpaceUnderLeftStack();
                    _hero.Move(Enums.Keys.KeyLeft);
                    _gameEngine.CheckIsFreeRouteLeft();
                    return;
                }
                if (buttonsPressed[(int)Keys.Up] && !_hero.Stacked)
                {
                    if (!spriteChanging.Enabled)
                    {
                        startIndexForSprites = -1;
                        endIndexForSprites = -2;
                        spriteChanging.Start();
                    }
                    _hero.Jumping = true;
                    _hero.Move(Enums.Keys.KeyUp);
                    return;
                }

                keysPressedWhileMoving.Clear();
                heroMoving.Stop();
                for (int i = 0; i < buttonsPressed.Length; i++)
                {
                    buttonsPressed[i] = false;
                }
                application.DrawingBox.Refresh();
            }
            else
            {
                spriteChanging.Stop();
                if (buttonsPressed[(int)Keys.Up])
                {
                    if (keysPressedWhileMoving.Count != 0 && keysPressedWhileMoving.Last().KeyCode!=Keys.Up)
                    {
                        buttonsPressed[(int)keysPressedWhileMoving.Last().KeyCode] = true;
                        _hero.Stacked = false;
                        _hero.GoBack = false;
                    }
                    else
                    {
                        _hero.Stacked = false;
                        
                        //heroMoving.Stop();
                    }

                    buttonsPressed[(int)Keys.Up] = false;
                }
                else
                {
                    heroMoving.Stop();
                    heroMoving.Tag = "disabled";
                    _hero.Stacked = false;
                    for (int i = 0; i < buttonsPressed.Length; i++)
                    {
                        buttonsPressed[i] = false;
                    }
                    keysPressedWhileMoving.Clear();
                }
                
                
            }
            
        }

        void stackFalling_Tick(object sender, EventArgs e)
        {
            _gameEngine.StackFalling();
            application.DrawingBox.Invalidate();
            
        }

        void application_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            
            if (e.Handled)
            {
                return;
            }
            if (!heroMoving.Enabled)
            {
                buttonsPressed[(int)e.KeyCode] = true;
                heroMoving.Tag = "enabled";
                heroMoving.Start();
            }
            else
            {
                keysPressedWhileMoving.Add(e);
            }
            
            
            
            e.Handled = true;
            
        }

       
        void heroFalling_Tick(object sender, EventArgs e)
        {
            if (_hero.Fall && !heroMoving.Enabled && !_hero.GoBack)
            {
                _hero.GoBack = true;
                _hero.Fall = false;
                
                heroMoving.Start();
                heroMoving.Tag = "enabled";
            }
        }

        void spriteChanging_Tick(object sender, EventArgs e)
        {

            if (startIndexForSprites < 0 && endIndexForSprites < 0)
            {
                currentSprite = sprites.Last();
            }

            if (startIndexForSprites < endIndexForSprites)
            {
                currentSprite = sprites[startIndexForSprites];
                startIndexForSprites++;
            }
            if (startIndexForSprites == endIndexForSprites)
            {
                if (endIndexForSprites == 6)
                {
                    startIndexForSprites = 3;
                }
                if (endIndexForSprites == 3)
                {
                    startIndexForSprites = 0;
                }

            }



        }

        #endregion Events


        public void AllTimersStop()
        {
            stackFalling.Stop();
            heroMoving.Stop();
            heroFalling.Stop();
            checkMoving.Stop();

            Paused = true;
        }


        private void Initialization(MainApp app, Graphics graphics, List<Stack> stacks, System.Drawing.Point heroCoordinates)
        {

            _graphics = graphics;
            _stacks = stacks;
            application = app;
            _hero = new Hero()
            {
                CurrentPosition_X = heroCoordinates.X,
                CurrentPosition_Y = heroCoordinates.Y
            };

            _gameEngine = new Core.Logic.Engine(stacks, _hero);


            _gameEngine.DrawingField = new DrawingFieldStructure()
            {
                Height = application.DrawingBox.Height,
                Width = application.DrawingBox.Width
            };




            application.KeyDown += application_KeyDown;
            buttonsPressed = new bool[Enum.GetNames(typeof(Keys)).Length];

            stackFalling = new System.Windows.Forms.Timer();
            stackFalling.Interval = 40;
            stackFalling.Tick += stackFalling_Tick;
            stackFalling.Enabled = true;
            stackFalling.Tag = "enabled";

            heroMoving = new System.Windows.Forms.Timer();
            heroMoving.Interval = 20;
            heroMoving.Tick += heroMoving_Tick;
            heroMoving.Tag = "disabled";

            checkMoving = new System.Windows.Forms.Timer();
            checkMoving.Interval = 1;
            checkMoving.Enabled = true;
            checkMoving.Tick += checkMoving_Tick;
            checkMoving.Tag = "enabled";


            heroFalling = new System.Windows.Forms.Timer();
            heroFalling.Enabled = true;
            heroFalling.Interval = 1;
            heroFalling.Tick += heroFalling_Tick;
            heroFalling.Tag = "enabled";

            
            app.DrawingBox.Paint += DrawingBox_Paint;
            
           

            _gameEngine.CheckSideBySideStacks();
            _gameEngine.CheckBorders();

            _gameEngine.FixStacksNearBorders();
            _gameEngine.CheckRouteRight();
            _gameEngine.CheckRouteLeft();


            keysPressedWhileMoving = new List<KeyEventArgs>();


            
            sprites = new List<Image>();
            
            sprites.Add(Image.FromFile(PathFinder.GetFullPathToFile("Images\\hero_move_l_0.png")));
            sprites.Add(Image.FromFile(PathFinder.GetFullPathToFile("Images\\hero_move_l_1.png")));
            sprites.Add(Image.FromFile(PathFinder.GetFullPathToFile("Images\\hero_move_l_2.png")));
            sprites.Add(Image.FromFile(PathFinder.GetFullPathToFile("Images\\hero_move_r_0.png")));
            sprites.Add(Image.FromFile(PathFinder.GetFullPathToFile("Images\\hero_move_r_1.png")));
            sprites.Add(Image.FromFile(PathFinder.GetFullPathToFile("Images\\hero_move_r_2.png")));
            sprites.Add(Image.FromFile(PathFinder.GetFullPathToFile("Images\\hero_stay.png")));


            spriteChanging = new System.Windows.Forms.Timer();
            spriteChanging.Interval = 100;
            spriteChanging.Tick += spriteChanging_Tick;

            animation = new DestroyingAnimation(app);

            playersLeaderboard = new LeaderboardManager();

            _heroCreator = new HeroCreator();
            _stackCreator = new StackCreator();

           
            
        }

       

       


        
    }
}
